home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 310_02 / primitiv.c < prev    next >
Text File  |  1990-04-18  |  36KB  |  1,403 lines

  1. /* 
  2.     Little Smalltalk
  3.  
  4.     Primitive manager
  5.     timothy a. budd
  6.     10/84
  7.  
  8.         hashcode code written by Robert McConeghy
  9.             (who also wrote classes Dictionary, et al).
  10. */
  11. /*
  12.     The source code for the Little Smalltalk System may be freely
  13.     copied provided that the source of all files is acknowledged
  14.     and that this condition is copied with each file.
  15.  
  16.     The Little Smalltalk System is distributed without responsibility
  17.     for the performance of the program and without any guarantee of
  18.     maintenance.
  19.  
  20.     All questions concerning Little Smalltalk should be addressed to:
  21.  
  22.         Professor Tim Budd
  23.         Department of Computer Science
  24.         Oregon State University
  25.         Corvallis, Oregon
  26.         97331
  27.         USA
  28. */
  29.  
  30. # include "object.h"
  31.  
  32. # ifdef CURSES
  33. # include <curses.h>
  34. # endif
  35.  
  36. # include <stdio.h>
  37. # include <ctype.h>
  38. # include <math.h>
  39. # include <errno.h>
  40. # include "drive.h"
  41. # include "interp.h"
  42. # include "process.h"
  43. # include "block.h"
  44. # include "string.h"
  45. # include "symbol.h"
  46. # include "number.h"
  47. # include "file.h"
  48. # include "byte.h"
  49. # include "primitive.h"
  50.  
  51. extern int errno;
  52. extern int prntcmd;
  53. extern double modf();
  54. extern long time();
  55. extern object *lookup_class();
  56. extern process *runningProcess;
  57. extern int responds_to(), generality();
  58. extern class  *mk_class();
  59. extern object *o_object, *o_true, *o_false, *o_nil, *o_number, *o_magnitude;
  60.  
  61. object *primitive(primnumber, numargs, args)
  62. int primnumber, numargs;
  63. object **args;
  64. {    object *resultobj;
  65.     object *leftarg, *rightarg, *fnd_class(), *fnd_super();
  66.     int    leftint, rightint, i, j;
  67.     double leftfloat, rightfloat;
  68.     long   clock;
  69.     char   *leftp, *rightp, *errp;
  70.     class  *aClass;
  71.     bytearray *byarray;
  72.     struct file_struct *phil;
  73.     int    opnumber = primnumber % 10;
  74.     char   strbuffer[300], tempname[100];
  75.  
  76.     errno = 0;
  77.     /* first do argument type checking */
  78.     switch(i = (primnumber / 10)) {
  79.         case 0: /* misc operations */
  80.             if (opnumber <= 5 && numargs != 1) goto argcerror;
  81.             leftarg = args[0];
  82.             break;
  83.  
  84.         case 1: /* integer operations */
  85.         case 2: 
  86.             if (numargs != 2) goto argcerror;
  87.             rightarg = args[1];
  88.             if (! is_integer(rightarg)) goto argterror;
  89.             rightint = int_value(rightarg);
  90.         case 3: 
  91.             if (i == 3 && opnumber && numargs != 1) 
  92.                 goto argcerror;
  93.             leftarg = args[0];
  94.             if (! is_integer(leftarg)) goto argterror;
  95.             leftint = int_value(leftarg);
  96.             break;
  97.  
  98.         case 4: /* character operations */
  99.             if (numargs != 2) goto argcerror;
  100.             rightarg = args[1];
  101.             if (! is_character(rightarg)) goto argterror;
  102.             rightint = int_value(rightarg);
  103.         case 5: 
  104.             if (i == 5 && numargs != 1) goto argcerror;
  105.             leftarg = args[0];
  106.             if (! is_character(leftarg)) goto argterror;
  107.             leftint = int_value(leftarg);
  108.             break;
  109.  
  110.         case 6: /* floating point operations */
  111.             if (numargs != 2) goto argcerror;
  112.             rightarg = args[1];
  113.             if (! is_float(rightarg)) goto argterror;
  114.             rightfloat = float_value(rightarg);
  115.         case 7: 
  116.             if (i == 7 && numargs != 1) goto argcerror;
  117.         case 8:
  118.             if (i == 8 && opnumber < 8 && numargs != 1) 
  119.                 goto argcerror;
  120.             leftarg = args[0];
  121.             if (! is_float(leftarg)) goto argterror;
  122.             leftfloat = float_value(leftarg);
  123.             break;
  124.  
  125.         case 9: /* symbol operations */
  126.             leftarg = args[0];
  127.             if (! is_symbol(leftarg)) goto argterror;
  128.             leftp = symbol_value(leftarg);
  129.             break;
  130.  
  131.         case 10: /* string operations */
  132.             if (numargs < 1) goto argcerror;
  133.             leftarg = args[0];
  134.             if (! is_string(leftarg)) goto argterror;
  135.             leftp = string_value(leftarg);
  136.             if (opnumber && opnumber <= 3) {
  137.                 if (numargs != 2) goto argcerror;
  138.                 rightarg = args[1];
  139.                 if (! is_string(rightarg)) goto argterror;
  140.                 rightp = string_value(rightarg);
  141.                 }
  142.             else if ((opnumber >= 4) && (opnumber <= 6)) {
  143.                 if (numargs < 2) goto argcerror;
  144.                 if (! is_integer(args[1])) goto argterror;
  145.                 i = int_value(args[1])-1;
  146.                 if ((i < 0) || (i >= strlen(leftp)))
  147.                     goto indexerror;
  148.                 }
  149.             else if ((opnumber >= 7) && (numargs != 1))
  150.                 goto argcerror;
  151.             break;
  152.  
  153.         case 11: /* misc operations */
  154.             if ((opnumber == 1) || (opnumber == 2)) {
  155.                 if (is_bltin(args[0])) goto argterror;
  156.                 if (numargs < 2) goto argcerror;
  157.                 if (! is_integer(args[1])) goto argterror;
  158.                 i = int_value(args[1]);
  159.                 if (i < 1 || i > args[0]->size)
  160.                     goto indexerror;
  161.                 }
  162.             else if ((opnumber >= 4) && (opnumber <= 6)) {
  163.                 if (numargs != 1) goto argcerror;
  164.                 if (! is_integer(args[0])) goto argterror;
  165.                 i = int_value(args[0]);
  166.                 if (i < 0) goto indexerror;
  167.                 }
  168.             else if (opnumber >= 7) {
  169.                 if (numargs < 1) goto argcerror;
  170.                 if (! is_bytearray(args[0])) goto argterror;
  171.                 byarray = (bytearray *) args[0];
  172.                 if (opnumber >= 8) {
  173.                     if (numargs < 2) goto argcerror;
  174.                     if (! is_integer(args[1]))
  175.                         goto argterror;
  176.                     i = int_value(args[1]) - 1;
  177.                     if (i < 0 || i >= byarray->a_bsize)
  178.                         goto indexerror;
  179.                     }
  180.                 }
  181.             break;
  182.  
  183.         case 12: /* string i/o operations */
  184.             if (opnumber < 6) {
  185.                 if (numargs < 1) goto argcerror;
  186.                 leftarg = args[0];
  187.                 if (! is_string(leftarg)) goto argterror;
  188.                 leftp = string_value(leftarg);
  189.                 }
  190.             break;
  191.  
  192.         case 13: /* operations on file */
  193.             if (numargs < 1) goto argcerror;
  194.             if (! is_file(args[0])) goto argterror;
  195.             phil = (struct file_struct *) args[0];
  196.             if (opnumber && (phil->fp == (FILE *) NULL)) {
  197.                 errp = "file must be open for operation";
  198.                 goto return_error;
  199.                 }
  200.             break;
  201.  
  202.         case 15: /* operations on classes */
  203.             if (opnumber < 3 && numargs != 1) goto argcerror;
  204.             if (! is_class(args[0])) goto argterror;
  205.             aClass = (class *) args[0];
  206.             break;
  207.  
  208. # ifdef PLOT3
  209.         case 17: /* plot(3) interface */
  210.             if (opnumber && opnumber <= 3) {
  211.                 if (numargs != 2) goto argcerror;
  212.                 if ((! is_integer(args[0])) || 
  213.                     (! is_integer(args[1])))
  214.                     goto argterror;
  215.                 leftint = int_value(args[0]);
  216.                 rightint = int_value(args[1]);
  217.                 }
  218.             else if ((opnumber == 6) || (opnumber == 7)) {
  219.                 if (numargs != 4) goto argcerror;
  220.                 for (i = 0; i < 4; i++)
  221.                     if (! is_integer(args[i]))
  222.                         goto argterror;
  223.                 leftint = int_value(args[0]);
  224.                 rightint = int_value(args[1]);
  225.                 i = int_value(args[2]);
  226.                 j = int_value(args[3]);
  227.                 }
  228.             else if (opnumber >= 8) {
  229.                 if (numargs != 1) goto argcerror;
  230.                 if (! is_string(args[0])) goto argterror;
  231.                 leftp = string_value(args[0]);
  232.                 }
  233.             break;
  234. # endif
  235.         }
  236.  
  237.  
  238.     /* now do operation */
  239.     switch(primnumber) {
  240.  
  241.         case 1:        /* class of object */
  242.             resultobj = fnd_class(args[0]);
  243.             if (resultobj) goto return_obj;
  244.             else goto return_nil;
  245.  
  246.         case 2:        /* get super_object */
  247.             resultobj = fnd_super(args[0]);
  248.             if (resultobj) goto return_obj;
  249.             else goto return_nil;
  250.  
  251.         case 3:        /* see if class responds to new */
  252.             leftint = 0;
  253.             if (! is_class(args[0])) goto return_boolean;
  254.             leftint = responds_to("new", (class *) args[0]);
  255.             goto return_boolean;
  256.  
  257.         case 4:        /* compute size of object */
  258.             leftint = args[0]->size;
  259.             goto return_integer;
  260.  
  261.         case 5:        /* return hashnum of object */
  262.             if (is_integer(leftarg))
  263.                 leftint = int_value(leftarg);
  264.             else if (is_character(leftarg))
  265.                 leftint = int_value(leftarg);
  266.             else if (is_symbol(leftarg))
  267.                 leftint = (int) symbol_value(leftarg);
  268.             else if (is_string(leftarg)) {
  269.                 leftp = string_value(leftarg);
  270.                 leftint = 0;
  271.                 for(i = 0; *leftp != 0; leftp++){
  272.                     leftint += *leftp;
  273.                     i++;
  274.                     if(i > 5)
  275.                        break;
  276.                     }
  277.                 }
  278.             else /* for all other objects return address */
  279.                 leftint = (int) &leftarg;
  280.             if (leftint < 0)
  281.                 leftint = -leftint;
  282.             goto return_integer;
  283.  
  284.         case 6:        /* built in object type testing */
  285.             if (numargs != 2) goto argcerror;
  286.             leftint = 0;
  287.             if (is_bltin(args[0]) == is_bltin(args[1]))
  288.                 if (is_bltin(args[0]))
  289.                     leftint = (args[0]->size == args[1]->size);
  290.                 else leftint = (args[0]->class == args[1]->class);
  291.             goto return_boolean;
  292.  
  293.         case 7:        /* object equality testing */
  294.             if (numargs != 2) goto argcerror;
  295.             leftint = (args[0] == args[1]);
  296.             goto return_boolean;
  297.  
  298.         case 8: